﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Text;
using System.Threading;

namespace MY.GPS
{
    public class ThreadPool
    {
        //线程池是否可用
        bool PoolEnable = false;

        //线程的容器
        List<Thread> ThreadContainer = null;

        //任务的容器
        ConcurrentQueue<ActionData> JobContainer = null;

        public ThreadPool (int threadNumber)
        {
            PoolEnable = true;
            ThreadContainer = new List<Thread>(threadNumber);
            JobContainer = new ConcurrentQueue<ActionData>();

            for(int i=0;i<threadNumber;i++)
            {
                Thread t = new Thread(RunJob);
                ThreadContainer.Add(t);
                t.Start();
            }
        }

        //向线程池添加一个任务
        public void AddTask(Action<object> job,object obj,Action<Exception> errorCallBack=null)
        {
            if(JobContainer!=null)
            {
                JobContainer.Enqueue(new ActionData { Job = job, Data = obj, ErrorCallBack = errorCallBack });
            }
        }

        //终止线程池
        public void FinalPool()
        {
            PoolEnable = false;
            JobContainer = null;
            if(ThreadContainer != null)
            {
                foreach (var item in ThreadContainer)
                {
                    item.Join();
                }
                ThreadContainer = null;
            }
        }

        private void RunJob()
        {
            while (JobContainer !=null && PoolEnable)
            {
                //任务列表取任务
                ActionData job = null;
                JobContainer?.TryDequeue(out job);

                if (job == null)
                {
                    //如果没有任务则休眠
                    Thread.Sleep(10);
                    continue;
                }
                try
                {
                    //执行任务
                    job.Job.Invoke(job.Data);
                }
                catch (Exception err)
                {

                    job?.ErrorCallBack(err);
                }
            } 
        }
    }
}
